package com.example.sharding.jdbc.demo.config;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.provider.AbstractDataSourceProvider;
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import com.example.sharding.jdbc.demo.constants.DSConstants;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Map;

/**
 * 动态数据源配置
 *
 * @author airtrioa
 * @date 2021/4/22
 */
@Configuration
@AutoConfigureBefore({DynamicDataSourceAutoConfiguration.class, ShardingJdbcConfig.class})
public class DynamicDatasourceConfig {
  /**
   * 动态数据源配置项
   */
  private final DynamicDataSourceProperties properties;

  public DynamicDatasourceConfig(DynamicDataSourceProperties properties) {
    this.properties = properties;
  }

  @Lazy
  @Resource(name = DSConstants.TEST_LOG_DS_NAME)
  DataSource testLogDataSource;

  @Lazy
  @Resource(name = DSConstants.TEST_RECORD_DS_NAME)
  DataSource testRecordDataSource;

  @Bean
  public DynamicDataSourceProvider dynamicDataSourceProvider() {
    // 获取已经存在的数据源
    Map<String, DataSourceProperty> datasourceMap = properties.getDatasource();
    return new AbstractDataSourceProvider() {
      @Override
      public Map<String, DataSource> loadDataSources() {
        Map<String, DataSource> dataSourceMap = super.createDataSourceMap(datasourceMap);
        // 将 ShardingJdbc 管理的数据源也交给动态数据源管理
        dataSourceMap.put(DSConstants.TEST_LOG_DS_NAME, testLogDataSource);
        dataSourceMap.put(DSConstants.TEST_RECORD_DS_NAME, testRecordDataSource);
        return dataSourceMap;
      }
    };
  }

  /**
   * 将动态数据源设置为首选的
   * 当spring存在多个数据源时, 自动注入的是首选的对象
   *
   * @return 数据源
   */
  @Primary
  @Bean
  public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
    DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
    dataSource.setPrimary(properties.getPrimary());
    dataSource.setStrict(properties.getStrict());
    dataSource.setStrategy(properties.getStrategy());
    dataSource.setProvider(dynamicDataSourceProvider);
    dataSource.setP6spy(properties.getP6spy());
    dataSource.setSeata(properties.getSeata());
    return dataSource;
  }
}
